<?php
/**
 * Created By virus_cms
 * Author: Virus
 * Date: 2020/3/23
 * Time: 16:04
 */

namespace app\common\lib;
use app\common\model\mysql\Category;

class Tree
{

    /**
     * @var object 对象实例
     */
    protected static $instance;

    /**
     * @var array 存放无限级分类的结果
     */
    public static $treeList = [];

    protected static $config = [
        "id"    => "id",  // id
        "pid"   => "pid", // pid
        "title" => "title", // 标题名称
        "child" => "child", // 子元素键名
        "html"  => "┝ ", // 层级标记
        "step"  => 4, // 层级步进数量
    ];

    /**
     * 构造函数
     * Tree constructor.
     * @param array $config
     */
    public function __construct($config = [])
    {
        self::$config = array_merge(self::$config, $config);
    }

    /**
     * 参数配置
     * @param array $config
     * @return Tree|object
     */
    public static function config($config = [])
    {
        if (!empty($config)) {
            $config = array_merge(self::$config, $config);
        }
        if (is_null(self::$instance)) {
            self::$instance = new static($config);
        }

        return self::$instance;
    }

    /**
     * @param $data
     * @param int $pid
     * @return array
     */
    public static function create($data, $pid = 0)
    {
        foreach ($data as $key => $value) {
            if ($value['pid'] == $pid) {
                self::$treeList[] = $value;
                unset($data[$key]);
                self::create($data, $value['id']);
            }
        }

        return self::$treeList;
    }

    /**
     * 将数据集格式化成层次结构
     * @param array $lists
     * @param int $pid
     * @param int $max_level
     * @param int $curr_level
     * @return array
     */
    public static function toLayer($lists = [], $pid = 0, $max_level = 0, $curr_level = 0)
    {
        $trees = [];
        $lists = array_values($lists);
        foreach ($lists as $key => $value) {
            if ($value[self::$config['pid']] == $pid) {
                if ($max_level > 0 && $curr_level == $max_level) {
                    return $trees;
                }
                unset($lists[$key]);
                $child = self::toLayer($lists, $value[self::$config['id']], $max_level, $curr_level + 1);
                if (!empty($child)) {
                    $value[self::$config['child']] = $child;
                }
                $trees[] = $value;
            }
        }

        return $trees;
    }

    /**
     * 将数据集格式化成列表结构
     * @param array $lists
     * @param int $pid
     * @param int $level
     * @return array
     */
    public static function toList($lists = [], $pid = 0, $level = 0)
    {
        if (is_array($lists)) {
            $trees = [];
            foreach ($lists as $key => $value) {
                if ($value[self::$config['pid']] == $pid) {
                    $title_prefix           = str_repeat(
                            "-",
                            $level * self::$config['step']
                        ).self::$config['html'];
                    $value['level']         = $level + 1;
                    $value['title_prefix']  = $level == 0 ? '' : $title_prefix;
                    $value['title_display'] = $level == 0 ? $value[self::$config['title']] : $title_prefix.$value[self::$config['title']];
                    $trees[]                = $value;
                    unset($lists[$key]);
                    $trees = array_merge($trees, self::toList($lists, $value[self::$config['id']], $level + 1));
                }
            }

            return $trees;
        } else {
            foreach ($lists as $key => $value) {
                if ($value[self::$config['pid']] == $pid && is_object($value)) {
                    $title_prefix           = str_repeat(
                            "&nbsp;",
                            $level * self::$config['step']
                        ).self::$config['html'];
                    $value['level']         = $level + 1;
                    $value['title_prefix']  = $level == 0 ? '' : $title_prefix;
                    $value['title_display'] = $level == 0 ? $value[self::$config['title']] : $title_prefix.$value[self::$config['title']];
                    $lists->offsetUnset($key);
                    $lists[] = $value;
                    self::toList($lists, $value[self::$config['id']], $level + 1);
                }
            }

            return $lists;
        }
    }

    /**
     * 根据子节点返回所有父节点
     * @param array $lists
     * @param string $id
     * @return array
     */
    public static function getParents($lists = [], $id = '')
    {
        $trees = [];
        foreach ($lists as $value) {
            if ($value[self::$config['id']] == $id) {
                $trees[] = $value;
                $trees   = array_merge(self::getParents($lists, $value[self::$config['pid']]), $trees);
            }
        }

        return $trees;
    }

    /**
     * 获取所有子节点id
     * @param array $lists
     * @param string $pid
     * @return array
     */
    public static function getChildsId($lists = [], $pid = '')
    {
        $result = [];
        foreach ($lists as $value) {
            if ($value[self::$config['pid']] == $pid) {
                $result[] = $value[self::$config['id']];
                $result   = array_merge($result, self::getChildsId($lists, $value[self::$config['id']]));
            }
        }

        return $result;
    }

    /**
     * 获取所有子节点
     * @param array $lists
     * @param string $pid
     * @return array
     */
    public static function getChilds($lists = [], $pid = '')
    {
        $result = [];
        foreach ($lists as $value) {
            if ($value[self::$config['pid']] == $pid) {
                $result[] = $value;
                $result   = array_merge($result, self::getChilds($lists, $value[self::$config['id']]));
            }
        }

        return $result;
    }

    /**
     * 根据子分类获取顶级分类
     * @param $id
     * @return mixed
     */
    public static function getNavPid($id)
    {
        $catId = Category::get($id);
        if ($catId['pid'] != 0) {
            return self::getNavPid($catId['pid']);
        }

        return $catId['id'];
    }
}